using System;
using Nemerle.Compiler;
using Colorblind.Common.PointerTypes;

namespace Colorblind.Common.Pointers {
	public class Pointer [T]
	where T : struct {
		public mutable Ptr : IPointer [T];
		public Value : T {
			get {
				Ptr.Value
			}
			
			set {
				Ptr.Value = value
			}
		}
		
		public this(addr : ulong = 0UL) {
			mutable foo : T;
			Ptr = (match(foo) {
				| _ is System.Byte => BytePointer() : object
				| _ is System.UInt16 => UShortPointer() : object
				| _ is System.UInt32 => UIntPointer() : object
				| _ is System.UInt64 => ULongPointer() : object
				| _ => null
			} :> IPointer [T]);
			Ptr.Addr = addr;
		}
		
		public this(addr : uint = 0U) {
			this(addr :> ulong);
		}
	}
	
	macro PointerMacro(decl, init) 
	syntax("pointer", decl, Optional("=", init)) {
		match(decl) {
			| TypeEnforcement(name, t) =>
				if(init == null)
					<[ def $name = Pointer.[$t](0UL) ]>;
				else
					<[ def $name = Pointer.[$t]($init) ]>;
		}
	}
	
	[assembly: Nemerle.Internal.OperatorAttribute ("Colorblind.Common.Pointers", "*", true, 160, 161)]
	macro @*(rval) {
		<[ ($(rval).Value) ]>
	}
}
